﻿
//运算类
//运算类包含所有运算的信息,如优先级,结合性等
//单目运算返回类型
//~ bit,bit uint?,uint?<<<<
//! bool,bool<<<<
//- sint?,sint? float,float<<<<
//+ sint?,sint? float,float<<<<
//(uint) uint?,sint?<<<<
//(sint) sint?,uing?<<<<
//(uint?) uint?,uint!<<<<
//(sint?) sint?,sint!<<<<
//++ uint?,uint? sint?,sint?<<<<
//-- uint?,uint? sint?,sint?<<<<

namespace n_PyOperation
{
using System;
using System.IO;
using n_PyVarType;
using n_PyET;
using n_OS;

public static class Operation
{
	//编译器启动初始化,加载运算信息文件
	public static void LoadFile()
	{
		//加载双目运算返回类型表
		string s = i_Compiler.Compiler.OpenCompileFile( n_PyConfig.Config.Path_pycompiler + "double_oper.lst" );
		s = s.Remove( s.IndexOf( "\n<end>" ) );
		string[] Lines = s.Split( '\n' );
		DoubleOper = new string[ Lines.Length ][ ];
		for( int i = 0; i < Lines.Length; ++i )
		{
			Lines[ i ] = Lines[ i ].Remove( Lines[ i ].IndexOf( "<<<<" ) );
			DoubleOper[ i ] = Lines[ i ].Split( ' ' );
		}
	}
	
	//判断第一个类型是否能隐式转换到第二个类型
	public static bool CanSwitch( string Type1, string Type2 )
	{
		string Uint = VarType.BaseType.Uint;
		string Sint = VarType.BaseType.Sint;
		if( VarType.BaseType.isUint( Type1 ) && VarType.BaseType.isUint( Type2 ) ) {
			Type1 = Type1.Remove( 0, Uint.Length );
			Type2 = Type2.Remove( 0, Uint.Length );
			if( int.Parse( Type1 ) < int.Parse( Type2 ) ) {
				return true;
			}
			return false;
		}
		if( VarType.BaseType.isSint( Type1 ) && VarType.BaseType.isSint( Type2 ) ) {
			Type1 = Type1.Remove( 0, Sint.Length );
			Type2 = Type2.Remove( 0, Sint.Length );
			if( int.Parse( Type1 ) < int.Parse( Type2 ) ) {
				return true;
			}
			return false;
		}
		if( VarType.isSysRefer( Type1 ) && VarType.isSysRefer( Type2 ) ) {
			return true;
		}
		return false;
	}
	
	//查找一个双目运算转换方式,没有的运算返回 null
	public static string GetSwitchType( string Oper, string Type1, string Type2 )
	{
		for( int i = 0; i < DoubleOper.Length; ++i ) {
			if( DoubleOper[ i ][ 0 ] != Oper ) {
				continue;
			}
			if( DoubleOper[ i ][ 1 ] == "left" ) {
				if( CanSwitch( Type2, Type1 ) ) {
					return "left";
				}
				return null;
			}
			if( DoubleOper[ i ][ 1 ] == "both" ) {
				if( CanSwitch( Type2, Type1 ) ) {
					return "left";
				}
				if( CanSwitch( Type1, Type2 ) ) {
					return "right";
				}
				return null;
			}
			if( DoubleOper[ i ][ 1 ] == "ignore" ) {
				return "no";
			}
		}
		ET.ShowError( "未定义的双目运算: " + Oper );
		return null;
	}
	
	//查找双目运算的参数类型
	public static string GetDoubleVarType( string TypeTemp, string Type )
	{
		string[] TypeCut = TypeTemp.Split( ',' );
		if( Type.IndexOf( ',' ) != -1 ) {
			return TypeCut[ 1 ];
		}
		if( VarType.BaseType.isUint( Type ) ) {
			if( CanSwitch( TypeCut[ 0 ], Type ) ) {
				return Type;
			}
			return TypeCut[ 0 ];
		}
		if( VarType.BaseType.isSint( Type ) ) {
			if( CanSwitch( TypeCut[ 1 ], Type ) ) {
				return Type;
			}
			if( TypeCut[ 1 ] == Type ) {
				return Type;
			}
			//... 这是一个危险的情况
			//ET.WriteLineError( 0,0, "ERROR! " + TypeTemp + "," + Type );
			return "overflow";
			//不要返回有符号常量的原始类型, 防止溢出
			//return TypeCut[ 1 ];
		}
		//这里是判断是否为bit类型, 0 或 1
		if( Type == VarType.BaseType.Bit && TypeCut.Length == 3 && TypeCut[ 2 ] == Type ) {
			return Type;
		}
		return TypeCut[ 1 ];
	}
	
	//查找一个双目运算的返回类型,没有的运算返回 null
	public static string GetDoubleReturnType( string Oper, string Type1, string Type2 )
	{
		if( Oper == "=" && Type1 == Type2 ) {
			return VarType.Void;
		}
		if( ( Oper == "+" || Oper == "-" || Oper == "*" || Oper == "/" || Oper == "%" ||
		      Oper == "+=" || Oper == "-=" || Oper == "*=" || Oper == "/=" || Oper == "%=" ) &&
		   Type1 == Type2 && Type1 != VarType.BaseType.Bit && Type1 != VarType.BaseType.Bool ) {
			return Type1;
		}
		if( ( Oper == ">" || Oper == "<" ) && Type1 == Type2 &&
		      Type1 != VarType.BaseType.Bit && Type1 != VarType.BaseType.Bool ) {
			return VarType.BaseType.Bool;
		}
		if( ( Oper == ">=" || Oper == "<=" ) &&
		   Type1 == Type2 &&
		   Type1 != VarType.BaseType.Bit && Type1 != VarType.BaseType.Bool && Type1 != VarType.BaseType.Float ) {
			return VarType.BaseType.Bool;
		}
		if( ( Oper == "==" || Oper == "!=" ) &&
		   Type1 == Type2 && Type1 != VarType.BaseType.Float ) {
			return VarType.BaseType.Bool;
		}
		if( ( Oper == "&" || Oper == "|" || Oper == "^" || Oper == "&=" || Oper == "|=" || Oper == "^=" ) &&
		   Type1 == Type2 && ( VarType.BaseType.isUint( Type1 ) || Type1 == VarType.BaseType.Bit ) ) {
			return Type1;
		}
		if( ( Oper == ">>" || Oper == "<<" || Oper == ">>=" || Oper == "<<=" ) &&
		  VarType.BaseType.isUint( Type1 ) && VarType.BaseType.isUint( Type2 ) ) {
			return Type1;
		}
		if( ( Oper == "&&" || Oper == "||" || Oper == "&&=" || Oper == "||=" ) &&
		   Type1 == Type2 && Type1 == VarType.BaseType.Bool ) {
			return VarType.BaseType.Bool;
		}
		return null;
	}
	
	//自动判断参数类型
	public static string GetSingleVarType( string Oper, string Type )
	{
		string Uint = VarType.BaseType.Uint;
		string Sint = VarType.BaseType.Sint;
		
		string[] TypeCut = Type.Split( ',' );
		if( Oper == "~" ) {
			return TypeCut[ 0 ];
		}
		if( Oper == "+" || Oper == "-" ) {
			return TypeCut[ 1 ];
		}
		if( Oper == "(" + Uint + ")" ) {
			return TypeCut[ 1 ];
		}
		if( Oper == "(" + Sint + ")" ) {
			return TypeCut[ 0 ];
		}
		return TypeCut[ 1 ];
	}
	
	//查找一个单目运算的返回类型,没有的运算返回 null
	public static string GetSingleReturnType( string Oper, string Type )
	{
		string Uint = VarType.BaseType.Uint;
		string Sint = VarType.BaseType.Sint;
		
		if( Oper == "~" && ( Type == VarType.BaseType.Bit || VarType.BaseType.isUint( Type ) ) ) {
			return Type;
		}
		if( Oper == "!" && Type == VarType.BaseType.Bool ) {
			return Type;
		}
		if( ( Oper == "+" || Oper == "-" ) && ( VarType.BaseType.isSint( Type ) || Type == VarType.BaseType.Float ) ) {
			return Type;
		}
		//如果是指针指向运算, 获取指针的目标类型
		if( Oper == "*" && VarType.isPointer( Type ) ) {
			Type = VarType.GetPointerMemberType( Type );
			Type = VarType.AddSysRefer( Type );
			return Type;
		}
		//如果是取地址运算, 生成指向目标类型的指针类型
		if( Oper == "&" ) {
			return VarType.AddPointerForType( Type );
		}
		if( Oper == "(" + Uint + ")" && VarType.BaseType.isSint( Type ) ) {
			return Type.Replace( Sint, Uint );
		}
		if( Oper == "(" + Sint + ")" && VarType.BaseType.isUint( Type ) ) {
			return Type.Replace( Uint, Sint );
		}
		if( ( Oper == "++" || Oper == "--" ) && ( VarType.BaseType.isUint( Type ) || VarType.BaseType.isSint( Type ) ) ) {
			return Type;
		}
		if( Oper.StartsWith( "(" + Uint ) && Oper != "(" + Uint + ")" ) {
			string TargetType = Oper.Remove( Oper.Length - 1 ).Remove( 0, 1 );
			if( VarType.BaseType.isUint( Type ) && Type != TargetType ) {
				return TargetType;
			}
		}
		if( Oper.StartsWith( "(" + Sint ) && Oper != "(" + Sint + ")" ) {
			string TargetType = Oper.Remove( Oper.Length - 1 ).Remove( 0, 1 );
			if( VarType.BaseType.isSint( Type ) && Type != TargetType ) {
				return TargetType;
			}
		}
		return null;
	}
	
	static string[][] DoubleOper;	//双目运算返回类型表
}
}



